#pragma once
#include "mysql.hpp"
#include "relation-odb.hxx"
#include "log.hpp"

#include <vector>
class RelationTable {
public:
    using ptr = std::shared_ptr<RelationTable>;
    RelationTable(const std::shared_ptr<odb::core::database> &db) : _db(db) {}


    bool insert(const std::string& user_id, const std::string& peer_id) {
        try {
            odb::transaction trans(_db->begin());
            Relation relation1(user_id, peer_id);
            Relation relation2(peer_id, user_id);
            _db->persist(relation1);
            _db->persist(relation2);
            trans.commit();
        }
        catch (const odb::exception &e) {
            LOG_ERROR("插入好友关系失败: {}-{}:{}", user_id, peer_id, e.what());
            return false;
        }
        LOG_INFO("插入好友关系成功: {}-{}", user_id, peer_id);
        return true;
    }


    bool remove(const std::string& user_id, const std::string& peer_id) {
        using query_t = odb::query<Relation>;
        try {
            odb::transaction trans(_db->begin());
            _db->erase_query<Relation>(query_t::user_id == user_id && query_t::peer_id == peer_id);
            _db->erase_query<Relation>(query_t::user_id == peer_id && query_t::peer_id == user_id);
            trans.commit();
        }
        catch(const odb::exception &e) {
            LOG_ERROR("删除好友关系失败: {}-{}:{}", user_id, peer_id, e.what());
            return false;
        }
        LOG_INFO("删除好友关系成功: {}-{}", user_id, peer_id);
        return true;
    }
    

    bool exists(const std::string& user_id, const std::string& peer_id) {
        using query_t = odb::query<Relation>;
        using result_t = odb::result<Relation>;
        bool ret = false;
        result_t r;
        try {
            odb::transaction trans(_db->begin());
            r = _db->query<Relation>(query_t::user_id == user_id && query_t::peer_id == peer_id);
            if(!r.empty())
                ret = true;
            trans.commit();
        }
        catch (const odb::exception &e) {
            LOG_ERROR("查询好友关系失败: {}-{}:{}", user_id, peer_id, e.what());
            return false;
        }
        return ret;
    }


    std::vector<std::string> friends(const std::string &user_id) {
        using query_t = odb::query<Relation>;
        using result_t = odb::result<Relation>;
        std::vector<std::string> ret;
        try {
            odb::transaction trans(_db->begin());
            result_t r = _db->query<Relation>(query_t::user_id == user_id);
            for(const auto& relation : r) {
                ret.emplace_back(relation.peer_id());
            }
            trans.commit();
        }
        catch (const odb::exception& e) {
            LOG_ERROR("查询好友列表失败: {}:{}", user_id, e.what());
            return {};
        }
        LOG_DEBUG("查询好友列表成功: {}:{}", user_id, ret.size());
        return ret;
    }
private:
    std::shared_ptr<odb::core::database> _db;
};